package cn.sangyy.gift.service.impl;

import cn.sangyy.gift.common.util.PageList;
import cn.sangyy.gift.constant.BaseConstant;
import cn.sangyy.gift.domain.TenantType;
import cn.sangyy.gift.mapper.TenantTypeMapper;
import cn.sangyy.gift.query.TenantTypeQuery;
import cn.sangyy.gift.service.ITenantTypeService;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author sangyy
 * @since 2023-06-20
 */
@Service
public class TenantTypeServiceImpl extends ServiceImpl<TenantTypeMapper, TenantType> implements ITenantTypeService {

    @Autowired
    private TenantTypeMapper tenantTypeMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;


    @Override
    public PageList<TenantType> selectPageList(TenantTypeQuery query) {
        Page<TenantType> page = new Page<>(query.getPage(),query.getRows());
        List<TenantType> rows = tenantTypeMapper.selectPageList(page,query);
        return new PageList<>(page.getTotal(),rows);
    }

    @Override
    public List<TenantType> selectList(Wrapper<TenantType> wrapper) {
        //从redis中查询，如果有直接返回
        Object o = redisTemplate.opsForValue().get(BaseConstant.TENANT_TYPES_CACHE_IN_REDIS);
        if(Objects.nonNull(o))
            return (List<TenantType>) o;
        //获取全局锁
        RLock lock = redissonClient.getLock(BaseConstant.TENANT_TYPES_CACHE_IN_REDIS);
        try {
            lock.lock();
            //在并发情况下等待的请求访问缓存有则直接返回
            o = redisTemplate.opsForValue().get(BaseConstant.TENANT_TYPES_CACHE_IN_REDIS);
            if(Objects.nonNull(o))
                return (List<TenantType>) o;
            List<TenantType> tenantTypes = super.selectList(null);
            if(tenantTypes == null || tenantTypes.size() < 1) {
                tenantTypes = new ArrayList<>();
            }
            redisTemplate.opsForValue().set(BaseConstant.TENANT_TYPES_CACHE_IN_REDIS,tenantTypes);
            return tenantTypes;

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if(lock != null){
                lock.unlock();
            }
        }
        return null;
    }

    @Override
    public boolean insert(TenantType entity) {
        super.insert(entity);
        //延迟双删保证数据一致性
        delayDoubleDelete();
        return true;
    }

    @Override
    public boolean deleteById(Serializable id) {
        super.deleteById(id);
        delayDoubleDelete();
        return true;
    }

    @Override
    public boolean updateById(TenantType entity) {
        super.updateById(entity);
        delayDoubleDelete();
        return true;
    }


    private void delayDoubleDelete() {
        redisTemplate.delete(BaseConstant.TENANT_TYPES_CACHE_IN_REDIS);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        redisTemplate.delete(BaseConstant.TENANT_TYPES_CACHE_IN_REDIS);
    }
}
